import threading
import time
import json
import logging
from base.client import BaseClient
from utils import RateLimiter, ConnectionConfig
from utils.exceptions import ConnectionError, AuthError
from .spi import TradeSpi

logger = logging.getLogger('trade.api')  # 细分日志类别

class TradeClient(BaseClient):
    """交易专用客户端"""
    def __init__(self, config: ConnectionConfig, spi: TradeSpi):
        super().__init__(config, spi)
        self._init_trade()
        self.__logged_in = False  # 登录状态
        self.__req_id = 0  # 请求ID计数器
        self.__user_id = "" #保存登录的用户

    def _init_trade(self):
        """交易特有初始化"""
        self._order_lock = threading.RLock()
        self._limiter = RateLimiter(
            max_calls=10,  # 10次/秒
            period=1
        )

    def _get_ws_url(self) -> str:
        return f"ws://{self.config.host}:{self.config.trade_port}"

    def _get_req_id(self):
        """获取递增的请求ID"""
        with self._order_lock:
            self.__req_id += 1
            return self.__req_id

    def send_order(self, order: dict):
        """发送订单"""
        with self._order_lock:
            self._limiter.acquire()
            self._validate_order(order)
            
            # 构建订单请求
            req = {
                "msgType": 5000,  # 委托请求
                "reqId": self._get_req_id(),
                "data": order
            }
            self._send(req)

    def _validate_order(self, order: dict):
        """订单校验"""
        required = ['symbol', 'price', 'quantity']
        if not all(f in order for f in required):
            raise ValueError("订单缺少必要字段")

    def _send(self, data: dict):
        """发送数据"""
        if not self.ws.sock or not self.ws.sock.connected:
            raise ConnectionError("交易连接未就绪")
        
        try:
            self.ws.send(json.dumps(data))
        except Exception as e:
            logger.error(f"数据发送失败: {str(e)}")
            self.reconnect()

    # 查询请求方法
    def req_qry_order(self, market = 0, securityId=""):
        """查询订单"""
        req = {
            "msgType": 6000,
            "reqId": self._get_req_id(),
            "data": {
                "market": market,
                "securityId": securityId
            }
        }
        logger.debug(f"发送查询订单请求: {req}")
        self._send(req)
    
    def req_qry_trade(self, market = 0, securityId=""):
        """查询成交"""
        req = {
            "msgType": 6002,
            "reqId": self._get_req_id(),
            "data": {
                "market": market,
                "securityId": securityId
            }
        }
        logger.debug(f"发送查询成交请求: {req}")
        self._send(req)
    
    def req_qry_position(self, market = 0, securityId=""):
        """查询持仓"""
        req = {
            "msgType": 6008,
            "reqId": self._get_req_id(),
            "data": {
                "market": market,
                "securityId": securityId
            }
        }
        logger.debug(f"发送查询持仓请求: {req}")
        self._send(req)
    
    def req_qry_account(self, acctType, accountId):
        """查询资金"""
        req = {
            "msgType": 6010,
            "reqId": self._get_req_id(),
            "data": {
                "userId": self.__user_id,
                "acctType": acctType,
                "accountId": accountId
            }
        }
        logger.debug(f"发送查询资金请求: {req}")
        self._send(req)
    
    def req_qry_strategy(self, plotid):
        """查询策略"""
        req = {
            "msgType": 6012,
            "reqId": self._get_req_id(),
            "data": {
                "plotid": plotid
            }
        }
        logger.debug(f"发送查询策略请求: {req}")
        self._send(req)
    
    def req_qry_instrument(self, market = 0, securityId=""):
        """查询合约"""
        req = {
            "msgType": 6014,
            "reqId": self._get_req_id(),
            "data": {
                "market": market,
                "securityId": securityId
            }
        }
        logger.debug(f"发送查询合约请求: {req}")
        self._send(req)

    def reconnect(self):
        """重新连接"""
        self.close()
        self._init_ws()
        self.connect()

    def connect(self):
        """重写连接流程，加入登录环节"""
        super().connect()
        self.__login()

    def __login(self):
        """执行登录认证（参考XWebTrd.c的AuthHandler）"""
        login_req = {
            "msgType": 3000,  # 登录消息类型
            "reqId": self._get_req_id(),
            "data": {
                "username": self.config.trade_username,
                "password": self.config.trade_password,
                "envType": 0,
                "version": "1.0.0",
                "veryCode": self.config.auth_code,
                "mac":""
            }
        }
        
        try:
            #保存登录时的用户Id
            self.__user_id = self.config.trade_username
            # 发送登录请求
            self._send(login_req)
            # 等待登录响应（参考XWebTrd.c的登录超时设置）
            if not self.__wait_login():
                raise AuthError("登录响应超时")
        except Exception as e:
            logger.error(f"登录失败: {str(e)}")
            self.close()
            raise

    def __wait_login(self, timeout: int = 15) -> bool:
        """等待登录响应（增加详细状态跟踪）"""
        logger.debug(f"开始等待登录响应，超时时间: {timeout}s")
        start = time.time()
        while time.time() - start < timeout:
            if self.__logged_in:
                logger.debug("检测到登录状态已更新")
                return True
            logger.debug(f"当前登录状态: {self.__logged_in}，等待中...")
            time.sleep(0.5)  # 增加状态轮询间隔
        logger.warning(f"登录响应超时，最后状态: {self.__logged_in}")
        return False

    def update_login_status(self, status: bool):
        """更新登录状态（由SPI回调触发）"""
        logger.debug(f"正在更新登录状态: {status}")
        self.__logged_in = status 
        if status:
            logger.info("登录状态已更新为已认证")
            ready_req = {
                "msgType": 1000,  # 就绪消息类型
                "reqId": self._get_req_id()
            }
            self._send(ready_req)

    def on_req_order(self, market, securityId, ordPrice, ordQty, bsType=1, ordType=1):
        """发送委托请求(5000)"""
        order_req = {
            "msgType": 5000,
            "reqId": self._get_req_id(),
            "data": {
                "userId": self.__user_id,
                "frontId": self._get_req_id(),
                "market": market,
                "securityId": securityId,
                "bsType": bsType,
                "ordPrice": ordPrice,
                "ordQty": ordQty,
                "ordType": ordType
            }
        }
        logger.debug(f"发送委托请求: {order_req}")
        self._send(order_req)
        return order_req["reqId"]

    def on_req_order_cancel(self, market, securityId, orgLocalId, orgOrdId):
        """发送委托请求撤单，已经封装过(5000)"""
        """撤单时orgLocalId和orgOrdId必须有一个有值"""
        order_req = {
            "msgType": 5000,
            "reqId": self._get_req_id(),
            "data": {
                "userId": self.__user_id,
                "frontId": self._get_req_id(),
                "market": market,
                "isCancel": 1,
                "securityId": securityId,
                "orgLocalId": orgLocalId,
                "orgOrdId": orgOrdId
            }
        }
        logger.debug(f"发送委托撤单请求: {order_req}")
        self._send(order_req)
        return order_req["reqId"]

    def on_req_strategy(self, strategy_name, strategy_type, parameters=None):
        """发送策略创建请求(7000)"""
        if parameters is None:
            parameters = {}
        
        create_req = {
            "msgType": 7000,
            "reqId": self._get_req_id(),
            "data": {
                "userId": self.__user_id,
                "strategyName": strategy_name,
                "strategyType": strategy_type,
                "parameters": parameters
            }
        }
        logger.debug(f"发送策略创建请求: {create_req}")
        self._send(create_req)
        return create_req["reqId"]

    def on_req_strategy_modify(self, plotid, param):
        """发送策略启动请求(7002)"""
        start_req = {
            "msgType": 7002,
            "reqId": self._get_req_id(),
            "data": {
                "userId":  self.__user_id,
                "strategyId": plotid,
                "parameters": param
            }
        }
        logger.debug(f"发送策略启动请求: {start_req}")
        self._send(start_req)
        return start_req["reqId"]

    def on_req_black_list(self, market, securityId, type=0):
        """发送黑名单请求(6016)"""
        black_list_req = {
            "msgType": 6016,
            "reqId": self._get_req_id(),
            "data": {
                "market": market,
                "securityId": securityId,
                "type": type
            }
        }
        logger.debug(f"发送黑名单请求: {black_list_req}")
        self._send(black_list_req)
        return black_list_req["reqId"]
